package com.zyl.file.util;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.File;

/**
 * @author zyl
 * @date 2023/9/8 11:12:04
 * @title
 * @description
 */
@Slf4j
public class FtpUtils {

    public static ChannelSftp getConnect(String host, int port, String username, String password) throws Exception {
        Session sshSession = null;
        ChannelSftp channel = null;
        JSch jsch = new JSch();
        jsch.getSession(username, host, port);
        //根据用户名，密码，端口号获取session
        sshSession = jsch.getSession(username, host, port);
        sshSession.setPassword(password);
        //修改服务器/etc/ssh/sshd_config 中 GSSAPIAuthentication的值yes为no，解决用户不能远程登录
        sshSession.setConfig("userauth.gssapi-with-mic", "no");
        //为session对象设置properties,第一次访问服务器时不用输入yes
        sshSession.setConfig("StrictHostKeyChecking", "no");
        sshSession.connect();
        //获取sftp通道
        channel = (ChannelSftp) sshSession.openChannel("sftp");
        channel.connect();
        return channel;
    }

    /**
     * @param channel   连接对象
     * @param directory 上传ftp的目录
     * @param input     文件流
     * @param fileName  文件名称
     */
    public static void upload(ChannelSftp channel, String directory, byte[] input, String fileName) {
        try {
            //执行列表展示ls 命令
            //执行盘符切换cd 命令
            mkdirDir(channel, directory.split(File.separator),"",directory.split(File.separator).length,0);
            channel.ls(directory);
            channel.cd(directory);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(input);
            channel.put(byteArrayInputStream, fileName);
            try {
                if (byteArrayInputStream != null) {
                    byteArrayInputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error(fileName + "关闭文件时.....异常!" + e.getMessage());
            }
        } catch (Exception e) {
            log.error("【子目录创建中】：", e);
            //创建子目录
            try {
                channel.mkdir(directory);
            } catch (SftpException ex) {
                ex.printStackTrace();
            }
        }
    }


    /**
     * 递归根据路径创建文件夹
     *
     * @param dirs     根据 / 分隔后的数组文件夹名称
     * @param tempPath 拼接路径
     * @param length   文件夹的格式
     * @param index    数组下标
     * @return
     */
    public static void mkdirDir(ChannelSftp channel, String[] dirs, String tempPath, int length, int index) {
        // 以"/a/b/c/d"为例按"/"分隔后,第0位是"";顾下标从1开始
        index++;
        if (index < length) {
            // 目录不存在，则创建文件夹
            tempPath += "/" + dirs[index];
        }
        try {
            log.info("检测目录[" + tempPath + "]");
            channel.cd(tempPath);
            if (index < length) {
                mkdirDir(channel,dirs, tempPath, length, index);
            }

        } catch (SftpException ex) {
            log.warn("创建目录[" + tempPath + "]");
            try {
                channel.mkdir(tempPath);
                channel.cd(tempPath);
            } catch (SftpException e) {
                e.printStackTrace();
                log.error("创建目录[" + tempPath + "]失败,异常信息[" + e.getMessage() + "]");

            }
            log.info("进入目录[" + tempPath + "]");
            mkdirDir(channel,dirs, tempPath, length, index);
        }

    }
}
